/**
 * 申请管理增强服务
 * 处理物料申请的创建、审批、归还等业务逻辑
 */

const Parse = require('parse/node');

class ApplicationService {
    /**
     * 获取申请列表
     * @param {Object} options - 查询选项
     * @returns {Promise<Object>} 申请列表和分页信息
     */
    static async getApplications(options = {}) {
        const {
            page = 1,
            pageSize = 10,
            status = '',
            userId = '',
            startDate = '',
            endDate = ''
        } = options;

        const Application = Parse.Object.extend('Application');
        const query = new Parse.Query(Application);

        // 添加筛选条件
        if (status) {
            query.equalTo('status', status);
        }

        if (userId) {
            const User = Parse.Object.extend('_User');
            const user = new User();
            user.id = userId;
            query.equalTo('applicant', user);
        }

        if (startDate) {
            query.greaterThanOrEqualTo('createdAt', new Date(startDate));
        }

        if (endDate) {
            query.lessThanOrEqualTo('createdAt', new Date(endDate));
        }

        // 关联查询
        query.include(['applicant', 'reviewer', 'items.material']);

        // 分页
        const total = await query.count();
        query.skip((page - 1) * pageSize);
        query.limit(pageSize);
        query.descending('createdAt');

        const applications = await query.find();

        return {
            data: applications.map(app => ({
                id: app.id,
                applicant: {
                    id: app.get('applicant').id,
                    username: app.get('applicant').get('username'),
                    name: app.get('applicant').get('name') || app.get('applicant').get('username')
                },
                items: app.get('items') || [],
                status: app.get('status'),
                purpose: app.get('purpose'),
                expectedReturnDate: app.get('expectedReturnDate'),
                actualReturnDate: app.get('actualReturnDate'),
                reviewer: app.get('reviewer') ? {
                    id: app.get('reviewer').id,
                    username: app.get('reviewer').get('username'),
                    name: app.get('reviewer').get('name') || app.get('reviewer').get('username')
                } : null,
                reviewNote: app.get('reviewNote'),
                reviewedAt: app.get('reviewedAt'),
                createdAt: app.get('createdAt'),
                updatedAt: app.get('updatedAt')
            })),
            total,
            page,
            pageSize,
            totalPages: Math.ceil(total / pageSize)
        };
    }

    /**
     * 创建申请
     * @param {Object} applicationData - 申请数据
     * @returns {Promise<Object>} 创建的申请
     */
    static async createApplication(applicationData) {
        const {
            userId,
            items,
            purpose,
            expectedReturnDate
        } = applicationData;

        // 验证用户
        const User = Parse.Object.extend('_User');
        const userQuery = new Parse.Query(User);
        const user = await userQuery.get(userId);
        if (!user) {
            throw new Error('用户不存在');
        }

        // 验证物料和库存
        const Material = Parse.Object.extend('Material');
        const materialQuery = new Parse.Query(Material);
        const materialIds = items.map(item => item.materialId);
        materialQuery.containedIn('objectId', materialIds);
        const materials = await materialQuery.find();

        if (materials.length !== materialIds.length) {
            throw new Error('部分物料不存在');
        }

        // 检查库存
        const stockCheck = items.map(item => {
            const material = materials.find(m => m.id === item.materialId);
            if (!material) {
                throw new Error(`物料 ${item.materialId} 不存在`);
            }
            if (material.get('stock') < item.quantity) {
                throw new Error(`物料 ${material.get('name')} 库存不足`);
            }
            return {
                materialId: item.materialId,
                materialName: material.get('name'),
                quantity: item.quantity,
                unit: material.get('unit'),
                status: 'pending'
            };
        });

        // 创建申请
        const Application = Parse.Object.extend('Application');
        const application = new Application();
        
        application.set('applicant', user);
        application.set('items', stockCheck);
        application.set('status', 'pending');
        application.set('purpose', purpose);
        application.set('expectedReturnDate', new Date(expectedReturnDate));

        const savedApplication = await application.save();

        // 记录操作日志
        await this.createOperationLog({
            type: 'application_created',
            applicationId: savedApplication.id,
            userId: userId,
            description: `创建申请，申请 ${items.length} 种物料`
        });

        return {
            id: savedApplication.id,
            applicant: {
                id: user.id,
                username: user.get('username'),
                name: user.get('name') || user.get('username')
            },
            items: stockCheck,
            status: 'pending',
            purpose,
            expectedReturnDate: new Date(expectedReturnDate),
            createdAt: savedApplication.get('createdAt')
        };
    }

    /**
     * 审批申请
     * @param {string} applicationId - 申请ID
     * @param {Object} approvalData - 审批数据
     * @returns {Promise<Object>} 审批结果
     */
    static async approveApplication(applicationId, approvalData) {
        const {
            action,
            reviewerId,
            reviewNote,
            items = []
        } = approvalData;

        // 获取申请
        const Application = Parse.Object.extend('Application');
        const query = new Parse.Query(Application);
        query.include(['applicant', 'items.material']);
        const application = await query.get(applicationId);

        if (!application) {
            throw new Error('申请不存在');
        }

        if (application.get('status') !== 'pending') {
            throw new Error('申请已处理，无法重复审批');
        }

        // 获取审批人
        const User = Parse.Object.extend('_User');
        const reviewerQuery = new Parse.Query(User);
        const reviewer = await reviewerQuery.get(reviewerId);

        if (!reviewer) {
            throw new Error('审批人不存在');
        }

        // 更新申请状态
        application.set('status', action);
        application.set('reviewer', reviewer);
        application.set('reviewNote', reviewNote);
        application.set('reviewedAt', new Date());

        if (action === 'approved') {
            // 通过审批，更新库存
            const Material = Parse.Object.extend('Material');
            const applicationItems = application.get('items');
            
            for (const item of applicationItems) {
                const materialQuery = new Parse.Query(Material);
                const material = await materialQuery.get(item.materialId);
                
                if (material) {
                    const currentStock = material.get('stock') || 0;
                    const newStock = currentStock - item.quantity;
                    
                    if (newStock < 0) {
                        throw new Error(`物料 ${material.get('name')} 库存不足`);
                    }
                    
                    material.set('stock', newStock);
                    await material.save();
                }
            }

            // 如果有指定的审批物料清单，更新申请物料
            if (items.length > 0) {
                application.set('items', items);
            }
        }

        const savedApplication = await application.save();

        // 记录操作日志
        await this.createOperationLog({
            type: `application_${action}`,
            applicationId: applicationId,
            userId: reviewerId,
            description: `${action === 'approved' ? '通过' : '拒绝'}申请：${reviewNote}`
        });

        return {
            id: savedApplication.id,
            status: action,
            reviewer: {
                id: reviewer.id,
                username: reviewer.get('username'),
                name: reviewer.get('name') || reviewer.get('username')
            },
            reviewNote,
            reviewedAt: savedApplication.get('reviewedAt')
        };
    }

    /**
     * 批量审批申请
     * @param {Array} applicationIds - 申请ID数组
     * @param {Object} approvalData - 审批数据
     * @returns {Promise<Object>} 批量审批结果
     */
    static async batchApprove(applicationIds, approvalData) {
        const results = [];
        const errors = [];

        for (const applicationId of applicationIds) {
            try {
                const result = await this.approveApplication(applicationId, approvalData);
                results.push(result);
            } catch (error) {
                errors.push({
                    applicationId,
                    error: error.message
                });
            }
        }

        return {
            success: results.length,
            failed: errors.length,
            results,
            errors
        };
    }

    /**
     * 归还物料
     * @param {string} applicationId - 申请ID
     * @param {Array} items - 归还物料列表
     * @param {string} note - 归还备注
     * @returns {Promise<Object>} 归还结果
     */
    static async returnMaterials(applicationId, items, note) {
        // 获取申请
        const Application = Parse.Object.extend('Application');
        const query = new Parse.Query(Application);
        query.include(['applicant']);
        const application = await query.get(applicationId);

        if (!application) {
            throw new Error('申请不存在');
        }

        if (application.get('status') !== 'approved') {
            throw new Error('只有已通过的申请才能归还物料');
        }

        // 更新库存
        const Material = Parse.Object.extend('Material');
        for (const item of items) {
            const materialQuery = new Parse.Query(Material);
            const material = await materialQuery.get(item.materialId);
            
            if (material) {
                const currentStock = material.get('stock') || 0;
                const newStock = currentStock + item.quantity;
                material.set('stock', newStock);
                await material.save();
            }
        }

        // 更新申请状态
        application.set('status', 'returned');
        application.set('actualReturnDate', new Date());
        application.set('returnNote', note);
        application.set('returnItems', items);

        const savedApplication = await application.save();

        // 记录操作日志
        await this.createOperationLog({
            type: 'application_returned',
            applicationId: applicationId,
            userId: application.get('applicant').id,
            description: `归还物料：${note}`
        });

        return {
            id: savedApplication.id,
            status: 'returned',
            actualReturnDate: savedApplication.get('actualReturnDate'),
            returnNote: note,
            returnItems: items
        };
    }

    /**
     * 获取申请统计数据
     * @returns {Promise<Object>} 统计数据
     */
    static async getApplicationStats() {
        const Application = Parse.Object.extend('Application');
        
        // 总申请数
        const totalQuery = new Parse.Query(Application);
        const total = await totalQuery.count();

        // 待审批申请数
        const pendingQuery = new Parse.Query(Application);
        pendingQuery.equalTo('status', 'pending');
        const pending = await pendingQuery.count();

        // 已通过申请数
        const approvedQuery = new Parse.Query(Application);
        approvedQuery.equalTo('status', 'approved');
        const approved = await approvedQuery.count();

        // 已归还申请数
        const returnedQuery = new Parse.Query(Application);
        returnedQuery.equalTo('status', 'returned');
        const returned = await returnedQuery.count();

        // 今日申请数
        const today = new Date();
        today.setHours(0, 0, 0, 0);
        const todayQuery = new Parse.Query(Application);
        todayQuery.greaterThanOrEqualTo('createdAt', today);
        const todayCount = await todayQuery.count();

        // 本周申请数
        const weekStart = new Date();
        weekStart.setDate(weekStart.getDate() - weekStart.getDay());
        weekStart.setHours(0, 0, 0, 0);
        const weekQuery = new Parse.Query(Application);
        weekQuery.greaterThanOrEqualTo('createdAt', weekStart);
        const weekCount = await weekQuery.count();

        // 本月申请数
        const monthStart = new Date();
        monthStart.setDate(1);
        monthStart.setHours(0, 0, 0, 0);
        const monthQuery = new Parse.Query(Application);
        monthQuery.greaterThanOrEqualTo('createdAt', monthStart);
        const monthCount = await monthQuery.count();

        return {
            total,
            pending,
            approved,
            returned,
            rejected: total - pending - approved - returned,
            todayCount,
            weekCount,
            monthCount,
            approvalRate: total > 0 ? (approved / total * 100).toFixed(1) : 0,
            returnRate: approved > 0 ? (returned / approved * 100).toFixed(1) : 0
        };
    }

    /**
     * 获取用户申请历史
     * @param {string} userId - 用户ID
     * @param {Object} options - 查询选项
     * @returns {Promise<Object>} 用户申请历史
     */
    static async getUserApplications(userId, options = {}) {
        const {
            page = 1,
            pageSize = 10,
            status = ''
        } = options;

        const User = Parse.Object.extend('_User');
        const user = new User();
        user.id = userId;

        const Application = Parse.Object.extend('Application');
        const query = new Parse.Query(Application);
        query.equalTo('applicant', user);

        if (status) {
            query.equalTo('status', status);
        }

        query.include(['reviewer']);
        
        const total = await query.count();
        query.skip((page - 1) * pageSize);
        query.limit(pageSize);
        query.descending('createdAt');

        const applications = await query.find();

        return {
            data: applications.map(app => ({
                id: app.id,
                items: app.get('items') || [],
                status: app.get('status'),
                purpose: app.get('purpose'),
                expectedReturnDate: app.get('expectedReturnDate'),
                actualReturnDate: app.get('actualReturnDate'),
                reviewer: app.get('reviewer') ? {
                    id: app.get('reviewer').id,
                    username: app.get('reviewer').get('username'),
                    name: app.get('reviewer').get('name') || app.get('reviewer').get('username')
                } : null,
                reviewNote: app.get('reviewNote'),
                reviewedAt: app.get('reviewedAt'),
                createdAt: app.get('createdAt'),
                updatedAt: app.get('updatedAt')
            })),
            total,
            page,
            pageSize,
            totalPages: Math.ceil(total / pageSize)
        };
    }

    /**
     * 创建操作日志
     * @param {Object} logData - 日志数据
     * @returns {Promise<Object>} 创建的日志
     */
    static async createOperationLog(logData) {
        const {
            type,
            applicationId,
            userId,
            description
        } = logData;

        const OperationLog = Parse.Object.extend('OperationLog');
        const log = new OperationLog();

        log.set('type', type);
        log.set('applicationId', applicationId);
        log.set('userId', userId);
        log.set('description', description);
        log.set('createdAt', new Date());

        return await log.save();
    }

    /**
     * 获取操作日志
     * @param {Object} options - 查询选项
     * @returns {Promise<Object>} 操作日志列表
     */
    static async getOperationLogs(options = {}) {
        const {
            page = 1,
            pageSize = 10,
            applicationId = '',
            userId = '',
            type = ''
        } = options;

        const OperationLog = Parse.Object.extend('OperationLog');
        const query = new Parse.Query(OperationLog);

        if (applicationId) {
            query.equalTo('applicationId', applicationId);
        }

        if (userId) {
            query.equalTo('userId', userId);
        }

        if (type) {
            query.equalTo('type', type);
        }

        const total = await query.count();
        query.skip((page - 1) * pageSize);
        query.limit(pageSize);
        query.descending('createdAt');

        const logs = await query.find();

        return {
            data: logs.map(log => ({
                id: log.id,
                type: log.get('type'),
                applicationId: log.get('applicationId'),
                userId: log.get('userId'),
                description: log.get('description'),
                createdAt: log.get('createdAt')
            })),
            total,
            page,
            pageSize,
            totalPages: Math.ceil(total / pageSize)
        };
    }
}

module.exports = ApplicationService;
